package com.fingard.dsp.bank.directbank.ceb11;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.helpers.YBTHelper;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.FtpPortClient;
import com.fingard.net.FtpReceiver;
import com.fingard.net.ftp.BizFtpClient;
import com.fingard.net.ftp.BizFtpResp;
import com.fingard.text.StringHelper;

import java.io.BufferedReader;
import java.io.File;
import java.io.StringReader;
import java.text.MessageFormat;
import java.util.Date;

/**
 * CEB11-光大银保通
 * <p>
 * 需求：批量代收付接口
 * 描述：只支持行内代收、代付，当天内即可回盘，准实时接口
 * 交互：字符集-GBK，通讯方式-FTP，数据格式-文本文件、换行符-'\n'，域分隔符-'|';
 *
 * @author Cruise
 * @date 2018/10/18
 */
public class CEB11BatPayRec extends CEB11Base implements IBatPayRec {
    @Override
    public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
        return d_BatPayRec(p_req1988);
    }

    @Override
    public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
        return d_QryBatPayRec(p_req1998);
    }

    @Override
    public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
        return d_BatPayRec(p_req9188);
    }

    @Override
    public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
        return d_QryBatPayRec(p_req9198);
    }

    /**
     * 批量代收付提交
     *
     * <p>
     * 功能描述:
     * </p>
     * <ul>
     * <li>1、文件名命名规则:</li>
     * <li>CEBPK/PF+4位保险机构标示+8位日期+4位序号.txt</li>
     * <li>2、文件内容格式说明:</li>
     * <li>1) 汇总记录：</li>
     * <li>CEB+PK/PF+4位保险机构标示+8位日期+4位序号|6位总笔数|18位总金额|\n</li>
     * <li>2) 明细记录：</li>
     * <li>顺序号|帐号|客户姓名|金额|备注|\n</li>
     * </ul>
     *
     * @param p_reqBat 批量代收付请求对象
     * @return 批量代收付响应对象
     * @throws Exception
     */
    public RetAtsBatPayRec d_BatPayRec(ReqBatPayRec p_reqBat) throws Exception {
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_reqBat.reqHeader);
        retAts.reqSeqID = p_reqBat.reqBatchNO;

        try {
            // 代收付文件内容
            StringBuilder sbFileContent = new StringBuilder();

            Date tmpDateNow = getDayCutTime(p_reqBat.getPayDateTime());
            String tmpPaySendDate = Format.Date8Format.format(tmpDateNow);

            String transType = "";
            String tmpDirType = "";
            if ("1988".equals(p_reqBat.reqHeader.transType)) {
                transType = "PF";
                tmpDirType = "pay";
            } else {
                transType = "PK";
                tmpDirType = "rec";
            }

            String totalNum = String.format("%6s", p_reqBat.totalNum).replace(" ", "0");
            String tmpBatSeqNo = YBTHelper.getBatSeqNo(getTempFileDirectory(tmpDateNow) + File.separator + tmpDirType, 4);

            // 汇总信息：CEB+PK/PF+4位保险机构标示+8位日期+4位序号|6位总笔数|18位总金额|
            String tmpReqHeader = MessageFormat.format("CEB{0}{1}{2}{3}|{4}|{5}|", transType, bankFront.corpNo,
                    tmpPaySendDate, tmpBatSeqNo, totalNum, p_reqBat.totalAmt);
            sbFileContent.append(tmpReqHeader);

            // 文件明细
            int tmpSeqNo = 0;
            while (p_reqBat.readRecord()) {
                if (sbFileContent.length() > 0) {
                    sbFileContent.append("\n");
                }

                String eachSeqNo = String.format("%6s", ++tmpSeqNo).replace(" ", "0");
                String oppAct = "";
                String oppName = "";
                if ("1988".equals(p_reqBat.reqHeader.transType)) {
                    oppAct = p_reqBat.readedDetail.recAct;
                    oppName = p_reqBat.readedDetail.recName;
                } else {
                    oppAct = p_reqBat.readedDetail.payAct;
                    oppName = p_reqBat.readedDetail.payName;
                }
                String payAmt = p_reqBat.readedDetail.payAmount;
                String postScript = p_reqBat.readedDetail.askNumber;

                // 明细信息:顺序号|帐号|客户姓名|金额|备注|
                String tmpReqBodyDetail = MessageFormat.format("{0}|{1}|{2}|{3}|{4}|", eachSeqNo, oppAct, oppName, payAmt, postScript);
                sbFileContent.append(tmpReqBodyDetail);
            }
            WriteBankLogLn2("批次文件内容:\r\n" + sbFileContent.toString());

            // 上传文件保存本地: CEBPK/PF+4位保险机构标示+8位日期+4位序号.txt
            String tmpUploadFileName = "CEB" + transType + bankFront.corpNo + tmpPaySendDate + tmpBatSeqNo + ".txt";
            String tmpLocalMarkPath = getTempFileDirectory(tmpDateNow) + File.separator + tmpDirType + File.separator + tmpUploadFileName;
            WriteBankLogLn2("批次文件保存本机路径: " + tmpLocalMarkPath);

            if (FileHelper.existFile(tmpLocalMarkPath)) {
                retAts.respCode = "0";
                retAts.respInfo = "本地批次文件已上传,请勿重复上传!";
                retAts.reqSeqID = p_reqBat.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = FailCode.E9981;
                retAts.writeRetToATS();
                return retAts;
            }

            FileHelper.writeFile(tmpLocalMarkPath, sbFileContent.toString(), getCharset());

            // 批次流水映射存入本地
            WriteBankLogLn2("批次流水映射文件内容:\r\n" + tmpBatSeqNo);
            String tmpBatSeqNoFilePath = getDataFileDirectory(tmpDateNow) + File.separator + p_reqBat.reqBatchNO + ".txt";
            WriteBankLogLn2("本地批次流水映射文件路径:" + tmpBatSeqNoFilePath);
            FileHelper.writeFile(tmpBatSeqNoFilePath, tmpBatSeqNo, getCharset());

            retAts.respCode = "0";
            retAts.reqSeqID = p_reqBat.reqBatchNO;

            // 上送银保通服务器
			/*
			FtpPortClient ftpPortClient = new FtpPortClient(ftpSet);
			FtpReceiver ftpReceiver = ftpPortClient.uploadFile(tmpLocalMarkPath, tmpUploadFileName);
			if (!ftpReceiver.isCompleted) {
				retAts.respCode = "-1";
				retAts.respInfo = ftpReceiver.connMsg;
			} else if (ConnState.FAIL.equals(ftpReceiver.connState)) {
				retAts.respInfo = "上传失败";
				retAts.transState = "BatchFailed";
				retAts.payInfoCode = "E9999";
			} else {
				retAts.respInfo = "上传成功";
				retAts.transState = "Uploaded";
				retAts.payInfoCode = "I4001";
			}
			*/
            FtpSet ftpSet = bankFront.getFtpSet("bat");
            BizFtpClient bizFtp = new BizFtpClient(ftpSet);
            try {
                bizFtp.connectAndLogin();
            } catch (Exception ex) {
                WriteBankLogLn(ex);
                retAts.respInfo = ex.toString();
                bizFtp.close();
            }
            if (bizFtp.isLogin()) {
                byte[] upBytes = FileHelper.readFileBytes(tmpLocalMarkPath);
                BizFtpResp resp = new BizFtpResp();
                try {
                    int upResult = bizFtp.uploadFile(upBytes, ftpSet.upDir, tmpUploadFileName, resp);
                    if (upResult == 1) {
                        retAts.respInfo = "上传成功";
                        retAts.transState = "Uploaded";
                        retAts.payInfoCode = "I4001";
                    } else if (upResult == -1) {
                        retAts.respInfo = resp.msg;
                        retAts.transState = "BatchFailed";
                        retAts.payInfoCode = "E9999";
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = resp.msg;
                    }
                } catch (Exception ex) {
                    WriteBankLogLn(ex);
                    retAts.respCode = "-1";
                    retAts.respInfo = ex.toString();
                } finally {
                    bizFtp.close();
                }
            } else {
                retAts.transState = "BatchFailed";
                retAts.payInfoCode = "E9999";
            }
            WriteBankLogLn("ftp日志：\r\n" + bizFtp.sbLog);
        } catch (Exception ex) {
            //ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.writeRetToATS();
        return retAts;
    }

    /**
     * 批量代收付状态查询
     *
     * <p>
     * 功能描述:
     * </p>
     * <ul>
     * <li>--------------------------------接收结果文件-----------------------------------------</li>
     * <li>1、接收结果文件名命名规则:</li>
     * <li>CEBPK/PF+4位保险机构标示+8位日期+4位序号.rec</li>
     * <li>2、接收结果文件内容格式说明:</li>
     * <li>1) 正确返回：</li>
     * <li>YBT0000|文件读取正确|0|</li>
     * <li>2) 错误返回：</li>
     * <li>错误码|错误原因|出错行数|</li>
     * <li></li>
     * <li>--------------------------------转账结果文件------------------------------------------</li>
     * <li>3、转账结果文件名命名规则:</li>
     * <li>CEBPK/PF+4位保险机构标示+8位日期+4位序号.ok</li>
     * <li>4、转账结果文件内容格式说明:</li>
     * <li>1) 汇总记录：</li>
     * <li>CEB+PK/PF+4位机构标识+ 8位日期+4位序号|6位总笔数|18位总金额|6位成功笔数|18位成功转帐金额|\n</li>
     * <li>2) 明细记录：</li>
     * <li>顺序号|帐号|客户姓名|金额|备注|流水号|返回码|返回信息|\n</li>
     * </ul>
     *
     * @param p_reqQryBat
     * @return
     * @throws Exception
     */
    public RetAtsQryBatPayRec d_QryBatPayRec(ReqQryBatPayRec p_reqQryBat) throws Exception {
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_reqQryBat.reqHeader);
        retAts.reqSeqID = p_reqQryBat.reqBatchNO;

        try {
            String transType = "";
            if ("1998".equals(p_reqQryBat.reqHeader.transType)) {
                transType = "PF";
            } else {
                transType = "PK";
            }

            Date tmpDateNow = getDayCutTime(p_reqQryBat.getBgnDateTime());
            String tmpPaySendDate = Format.Date8Format.format(tmpDateNow);

            // 1、读取本地批次流水映射文件
            String tmpBatSeqNoPath = getDataFileDirectory(tmpDateNow) + File.separator + p_reqQryBat.reqBatchNO + ".txt";
            File tmpBatSeqNoFile = new File(tmpBatSeqNoPath);
            if (!tmpBatSeqNoFile.exists()) {
                retAts.respCode = "-1";
                retAts.respInfo = "批次流水映射文件[" + tmpBatSeqNoPath + "]不存在!";
                retAts.writeAfterDetail();
                return retAts;
            }

            String tmpSeqNoContent = FileHelper.readFileText(tmpBatSeqNoPath, getCharset());
            WriteBankLogLn2("本地批次流水映射文件内容:\r\n" + tmpSeqNoContent);
            if (StringHelper.isNullOrEmpty(tmpSeqNoContent)) {
                retAts.respCode = "-1";
                retAts.respInfo = "批次流水映射文件内容为空!";
                retAts.writeAfterDetail();
                return retAts;
            }

            // 接收结果文件：CEBPK/PF+4位保险机构标示+8位日期+4位序号.rec
            String tmpRecResultFile = "CEB" + transType + bankFront.corpNo + tmpPaySendDate + tmpSeqNoContent + ".rec";
            String tmpRecResultFilePath = getTempFileDirectory(tmpDateNow) + File.separator + tmpRecResultFile;

            FtpSet ftpSet = bankFront.getFtpSet("bat");
            FtpPortClient ftpPortClient = new FtpPortClient(ftpSet);
            FtpReceiver ftpReceiver = ftpPortClient.downloadFile(tmpRecResultFile, tmpRecResultFilePath);
            if (ftpReceiver.isCompleted) {
                String tmpResultFileContent = FileHelper.readFileText(tmpRecResultFilePath, getCharset());
                WriteBankLogLn2("接收结果文件内容:\r\n" + tmpResultFileContent);

                if (StringHelper.hasAnyChar(tmpResultFileContent)) {
                    String[] tmpResultFileArray = tmpResultFileContent.split("\\|");
                    if ("0".equals(tmpResultFileArray[2])) {
                        // 转账结果文件：CEBPK/PF+4位保险机构标示+8位日期+4位序号.ok
                        String tmpTransferResultFile = "CEB" + transType + bankFront.corpNo + tmpPaySendDate + tmpSeqNoContent + ".ok";
                        String tmpTransferResultFilePath = getTempFileDirectory(tmpDateNow) + File.separator + tmpTransferResultFile;
                        ftpReceiver = ftpPortClient.downloadFile(tmpTransferResultFile, tmpTransferResultFilePath);
                        if (ftpReceiver.isCompleted) {
                            String tmpTransferResultFileContent = FileHelper.readFileText(tmpTransferResultFilePath, getCharset());
                            WriteBankLogLn2("转账结果文件内容:\r\n" + tmpTransferResultFileContent);

                            if (StringHelper.hasAnyChar(tmpTransferResultFileContent)) {
                                retAts.respCode = "0";
                                retAts.reqSeqID = p_reqQryBat.reqBatchNO;

                                StringReader strReader = new StringReader(tmpTransferResultFileContent);
                                BufferedReader tmpReader = new BufferedReader(strReader);
                                tmpReader.readLine();

                                while (true) {
                                    String eachline = tmpReader.readLine();
                                    if (eachline == null) {
                                        break;
                                    }
                                    if (eachline.indexOf("|") > 0) {
                                        // 明细记录:顺序号|帐号|客户姓名|金额|备注|流水号|返回码|返回信息|
                                        String[] bodyValues = eachline.split("\\|");
                                        RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();

                                        if (p_reqQryBat.reqHeader.transType.equals("1998")) {
                                            tmpRetDetail.recAct = bodyValues[1];
                                            tmpRetDetail.recName = bodyValues[2];
                                        } else if (p_reqQryBat.reqHeader.transType.equals("9198")) {
                                            tmpRetDetail.payAct = bodyValues[1];
                                            tmpRetDetail.payName = bodyValues[2];
                                        }

                                        tmpRetDetail.postScript = bodyValues[4];
                                        tmpRetDetail.payAmount = bodyValues[3];
                                        tmpRetDetail.result = StringHelper.joinNotEmpty("+", "DT", bodyValues[6]);
                                        tmpRetDetail.payInfoCode = bodyValues[6];
                                        if (bodyValues.length > 7) {
                                            tmpRetDetail.memo = eachline.substring(getCharacterPosition(eachline, 7) + 1).replace("|", "");
                                        } else {
                                            // 支付成功不返回信息,需设置默认值
                                            tmpRetDetail.memo = "转账成功";
                                        }

                                        retAts.writeRetDetail(tmpRetDetail);
                                    } else {
                                        retAts.respCode = "-1";
                                        retAts.respInfo = "银行返回明细数据格式非法!";
                                    }
                                }
                            } else {
                                retAts.respCode = "-1";
                                retAts.respInfo = "转账结果文件[" + tmpTransferResultFile + "]内容为空!";
                            }
                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = ftpReceiver.connMsg;
                        }
                    } else {
                        retAts.respCode = "0";
                        retAts.respInfo = tmpResultFileArray[1];
                        retAts.transState = tmpResultFileArray[0];
                        retAts.payInfoCode = tmpResultFileArray[0];
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = "接收结果文件[" + tmpRecResultFile + "]内容为空!";
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = ftpReceiver.connMsg;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.writeAfterDetail();
        return retAts;
    }
}
